/************************************************************************************
**  
* @copyright (c) 2015-, Technology Co., LTD. All Right Reserved.
*
*************************************************************************************/
/**
* @file     duye_cap_udp_service.cpp
* @version     
* @brief      
* @author   
* @date     2013-01-09
* @note 
*
*  1. 2018-01-09 created this file
* 
*/
#include <duye_logger.h>
#include <duye_system.h>

#include <duye_cap_udp_service.h>

static const int8* DUYE_LOG_PREFIX = "duye.cap.udp.service";

namespace duye {

bool UdpServiceFilterWorker::filterPkt(const PacketReference& pktRef, const FilterRule& rule) {
	if (pktRef->getTfLayerProto() == rule.whiteRuleList().begin()->protocol()) {
		return true;
	}
	return false;
}

UdpService::UdpService() : CapDataService("UdpService") {
	FilterRule serviceRule;

	// udp filter rule
	RuleItem ruleItem;
	ruleItem.setProtocol(PROTO_UDP);

	// setting rules
	serviceRule.addWhiteRule(ruleItem);
	serviceRule.setFilterWorker(&m_filterWorker);

	NetLayerService::instance().addListener(this, &serviceRule);
}

UdpService::~UdpService() {
	for (UdpListenerMap::iterator iter = m_listenerMap.begin(); iter != m_listenerMap.end(); ++iter) {
		delete iter->second;
	}

	m_listenerMap.clear();
}

bool UdpService::start() {
	startTask();
	return true;
}

bool UdpService::stop() {
	return true;
}

bool UdpService::run() {
	DUYE_INFO("UdpService Start");

	for (;;) {
		DUYE_INFO("UdpService Working");
		System::sleep(10);
	}

	DUYE_INFO("UdpService Exit");

	return true;
}

bool UdpService::addListener(DataServiceListener* listener, const FilterRule* filterRule) {
	UdpListener* udpListener = dynamic_cast<UdpListener*>(listener);
	if (udpListener == NULL) {
		return false;
	}
	
	FilterRule* copyFilterRule = NULL;
	if (filterRule == NULL) {
		m_listenerMap.insert(std::make_pair(udpListener, copyFilterRule));
	} else {
		copyFilterRule = new FilterRule(*filterRule);
		m_listenerMap.insert(std::make_pair(udpListener, copyFilterRule));
	}

	return true;
}

bool UdpService::delListener(DataServiceListener* listener) {
	m_listenerMap.erase(dynamic_cast<UdpListener*>(listener));
	return true;
}

int32 UdpService::onNetLayerPacket(const PacketReference& pktRef) {
	if (pktRef.isNull()) {
		DUYE_ERROR("pktRef.isNull()");
		return -1;
	}

	if (pktRef->getTfLayerProto() != PROTO_UDP) {
		return -1;
	}

	DUYE_DEBUG("Protocol type(%d) is %s, src_port=%d dst_port=%d", 
		pktRef->getTfLayerProto(), 
		Protocols::instance().getName(pktRef->getTfLayerProto()).c_str(),
		pktRef->getSrcPort(), pktRef->getDstPort());

	const UdpSession& udpSession = findUdpSession(pktRef);
	for (UdpListenerMap::iterator iter = m_listenerMap.begin(); iter != m_listenerMap.end(); ++iter) {
		if (FilterEngine::instance().filterPkt(pktRef, iter->second)) {
			iter->first->onUdpPacket(pktRef);
			iter->first->onUdpSession(pktRef, udpSession);
		}
	}

	return 0;
}

const UdpSession& UdpService::findUdpSession(const PacketReference& pktRef) {
	static UdpSession udpSession;
	return udpSession;
}

}
